#pragma once

#include "Thread.hpp"
#include "Task.hpp"
#include "lockGuard.hpp"
#include <mutex>
#include <vector>
#include <queue>
#include <unistd.h>

static const int gnum = 5;
using namespace ThreadNs;

template <class T>
class ThreadPool;

template <class T>
class ThreadData
{
public:
    ThreadPool<T> *_threadpool;
    std::string _name;

public:
    ThreadData(ThreadPool<T> *threadpool, const std::string &name) : _threadpool(threadpool), _name(name)
    {
    }
};

template <class T>
class ThreadPool
{
private:
    static void *handlerTask(void *args) // 静态方法要把this传进来
    {
        // ThreadPool *threadpool = static_cast<ThreadPool *>(args);
        ThreadData<T> *td = (ThreadData<T> *)args;

        while (true)
        {
            T t;
            while (true)
            {
                { // td->_threadpool->lockQueue();
                    LockGuard lockguard(&td->_threadpool->_mutex);
                    while (td->_threadpool->isQueueEmpty())
                    {
                        td->_threadpool->threadWait();
                    }
                    t = td->_threadpool->pop(); // pop的本质：是将任务从公共队列中，拿到当前线程自己独立的栈中
                    // td->_threadpool->unlockQueue();}
                    std::cout << td->_name << " 获取了一个任务" << t.toTaskString() << " 并处理完成，结果是：" << t() << std::endl;
                }
            }
            delete td;
            return nullptr;
        }
    }

public:
    void lockQueue() { pthread_mutex_lock(&_mutex); }
    void unlockQueue() { pthread_mutex_unlock(&_mutex); }
    bool isQueueEmpty() { _task_queue.empty(); };
    void threadWait() { pthread_cond_wait(&_cond, &_mutex); }
    T pop()
    {
        T t = _task_queue.front();
        _task_queue.pop();
        return t;
    }
    ThreadPool(int num = gnum)
        : _num(num)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
        for (int i = 0; i < num; ++i)
        {
            _threads.push_back(new Thread());
        }
    }

public:
    void run()
    {
        for (const auto &t : _threads)
        {
            ThreadData<T> *td = new ThreadData<T>(this, t->threadname());
            t->start(handlerTask, td);
            std::cout << t->threadname() << "start..." << std::endl;
            // delete td;
        }
    }
    void push(const T &in)
    {
        LockGuard lockguard(&_mutex);
        // pthread_mutex_lock(&_mutex);
        _task_queue.push(in);
        pthread_cond_signal(&_cond);
        // pthread_mutex_unlock(&_mutex);
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        for (auto &t : _threads)
            delete t;
    }

    void operator=(const ThreadPool &tp) = delete;
    ThreadPool(const ThreadPool &tp) = delete;

    static ThreadPool<T> *getInstance() // 获取实例 -- 这个本来就是一个临界资源
    {
        if (_tp == nullptr)// 防止每次进来都要加锁
        {
            _sigle_mutx.lock();
            if (_tp == nullptr)
            {
                _tp = new ThreadPool<T>();
            }
            _sigle_mutx.unlock();
        }

        return _tp;
    }

private:
    int _num;                       // 线程个数
    std::vector<Thread *> _threads; // 用数组管理线程
    std::queue<T> _task_queue;      // 任务队列
    pthread_mutex_t _mutex;         // 需要一把锁，让线程竞争任务
    pthread_cond_t _cond;           // 没有任务的时候让线程休眠

    static ThreadPool<T> *_tp;
    static std::mutex _sigle_mutx;
};

template <class T>
ThreadPool<T> *ThreadPool<T>::_tp = nullptr;

template <class T>
std::mutex ThreadPool<T>::_sigle_mutx;